AWS Amplify Gen 2 で Cognito ユーザープールと DynamoDB テーブルの削除保護を有効化する

AWS Amplify Gen 2 で Cognito ユーザープールと DynamoDB テーブルの削除保護を有効化する

Clock Icon2024.08.19

いわさです。

最近とある Web システムを開発しようとしており、ユーザーが利用するポータル画面のようなものを Amplify を使って作成しようとしています。
運用を考えた時にユーザー情報やデータの保護をしておきたいと思いました。

該当リソースであるCognito ユーザープールや DynamoDB テーブルには削除保護の機能があります。

https://dev.classmethod.jp/articles/amazon-cognito-user-pool-delete-protection/

https://dev.classmethod.jp/articles/amazon-dynamodb-now-supports-delete-protection/

Amplify Gen 2 でデプロイされた環境(運用もサンドボックスも)はどちらも削除保護が無効化された状態でした。

CF133932-2E8E-4699-8D88-B0B01AD4F9CD.png

D263D72C-3E4E-4D3C-B80D-0B025F73740E.png

Amplify Gen 2 で実装するにはどうしたら良いのかと思っていたところ、Amplify 公式ドキュメントでしっかり対応方法が紹介されていました。

https://docs.amplify.aws/react/build-a-backend/add-aws-services/deletion-backup-resources/

バックエンドリソースの定義から CloudFormation リソースにアクセスしてプロパティの変更が出来るみたいです。プロパティ定義されていれば同様に何でもカスタマイズ出来るということか。なるほど...

変更してみる

backend.tsは Amplify で使われるバックエンドリソースを定義します。
以下では認証とデータのバックエンドがデフォルトで構成されていましてこれに伴って Cognito や AppSync、DynamoDB がデプロイされます。

以下ではドキュメントの手順どおりに Cognito ユーザープールのdeletionProtectionと、DynamoDB テーブルのdeletionProtectionEnabledを設定しています。

/amplify/backend.ts
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';

const backend = defineBackend({
  auth,
  data,
});

const { cfnUserPool } = backend.auth.resources.cfnResources
cfnUserPool.deletionProtection = "ACTIVE";

const { amplifyDynamoDbTables } = backend.data.resources.cfnResources;
for (const table of Object.values(amplifyDynamoDbTables)) {
  table.deletionProtectionEnabled = true;
}

では、サンドボックスを作成して確認してみましょう。

% npx ampx sandbox
[Sandbox] Pattern !.vscode/extensions.json found in .gitignore. ".vscode/extensions.json" will not be watched if other patterns in .gitignore are excluding it.

  Amplify Sandbox

:

(省略)

:

✨  Deployment time: 94.17s

Outputs:
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.allowUnauthenticatedIdentities = true
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.amplifyApiModelSchemaS3Uri = s3://amplify-amplifyvitereactt-amplifydataamplifycodege-vmkyglsxpvfn/model-schema.graphql
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.authRegion = ap-northeast-1
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.awsAppsyncAdditionalAuthenticationTypes = AMAZON_COGNITO_USER_POOLS,AWS_IAM
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.awsAppsyncApiEndpoint = https://zejqkprqfva4tjirxdklix3gni.appsync-api.ap-northeast-1.amazonaws.com/graphql
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.awsAppsyncApiId = epj7rb3rxvh4zco4nrljptmx5u
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.awsAppsyncApiKey = da2-hogehogehogehoge
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.awsAppsyncAuthenticationType = API_KEY
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.awsAppsyncRegion = ap-northeast-1
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.definedFunctions = ["amplify-amplifyvitereactte-presignuplambda88F2702A-uUNBfd9P1qdl"]
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.deploymentType = sandbox
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.identityPoolId = ap-northeast-1:8cc132ec-ffa2-4511-b440-41a6dd291530
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.mfaConfiguration = OFF
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.mfaTypes = []
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.oauthClientId = 3pk366gej73etvh8s77191qhih
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.oauthCognitoDomain = 
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.oauthRedirectSignIn = https://example.com
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.oauthRedirectSignOut = 
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.oauthResponseType = code
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.oauthScope = ["profile","phone","email","openid","aws.cognito.signin.user.admin"]
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.passwordPolicyMinLength = 8
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.passwordPolicyRequirements = ["REQUIRES_NUMBERS","REQUIRES_LOWERCASE","REQUIRES_UPPERCASE","REQUIRES_SYMBOLS"]
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.region = ap-northeast-1
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.signupAttributes = ["email"]
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.socialProviders = 
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.userPoolId = ap-northeast-1_IeO97bu4h
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.usernameAttributes = ["email"]
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.verificationMechanisms = ["email"]
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8.webClientId = 3pk366gej73etvh8s77191qhih
Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789012:stack/amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8/687996f0-5c76-11ef-9f35-0614f7d9ff0f

✨  Total time: 94.19s

[Sandbox] Watching for file changes...
File written: amplify_outputs.json

サンドボックス環境が再構築されました。
上記に出力されている Cognito ユーザープールを確認してみます。
次のように Cognito ユーザープールの削除保護が有効化されていました。

53628AA7-678B-48B0-93FB-2017BB4D7ABF.png

続いて、上記に出力されている AppSync に紐づいている DynamoDB の削除保護を確認してみます。
Amplify から直接 DynamoDB の参照はされていないので上記構成には登場しません。サンドボックスの AppSync リソースは確認出来るので、そのデータソースからサンドボックス用の DynamoDB テーブルを特定することが出来ます。

3A1993E8-0C03-45E5-9014-EA82A326FB83.png

こちらも削除保護が有効化されていました。良いですね。

EB83311A-96A4-4FC5-A5FF-FB9CF671E089.png

サンドボックス削除に失敗する

起動したサンドボックス環境は Ctrl + C などで終了させた時に環境を削除(デプロイした AWS リソースを削除)することが出来ます。
ドキュメントにも記載されているのですが、今回の削除保護機能を有効化するとサンドボックスの削除に失敗するようです。

試してみましょう。

[Sandbox] Watching for file changes...
File written: amplify_outputs.json
? Would you like to delete all the resources in your sandbox environment (This cannot be undone)? y
[Sandbox] Deleting all the resources in the sandbox environment...

:

(省略)

:

Failed resources:
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8-auth179371D7-CKCMWYYRRWDE | 7:14:37 AM | DELETE_FAILED        | AWS::Cognito::UserPool     | auth/amplifyAuth/UserPool (amplifyAuthUserPool4BA7F805) Resource handler returned message: "The user pool cannot be deleted because deletion protection is activated. Deletion protection must be inactivated first. (Service: CognitoIdentityProvider, Status Code: 400, Request ID: bbfa078c-545b-43c8-884b-2ed63ad0e3bc)" (RequestToken: 042545c0-aa20-d039-b03d-cf3718608589, HandlerErrorCode: InvalidRequest)
amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8 | 7:14:38 AM | DELETE_FAILED        | AWS::CloudFormation::Stack | auth.NestedStack/auth.NestedStackResource (auth179371D7) Embedded stack arn:aws:cloudformation:ap-northeast-1:123456789012:stack/amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8-auth179371D7-CKCMWYYRRWDE/7f8ce090-5c76-11ef-a532-06609bc6ea93 was not successfully deleted: The following resource(s) failed to delete: [amplifyAuthUserPool4BA7F805]. 

UnknownFault: Error: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!                                                                            !!
!!  Node 21 has reached end-of-life on 2024-06-01 and is not supported.       !!
!!  Please upgrade to a supported node version as soon as possible.           !!
!!                                                                            !!
!!  This software is currently running on node v21.7.1.                       !!
!!  As of the current release of this software, supported node releases are:  !!
!!  - ^22.0.0 (Planned end-of-life: 2027-04-30)                               !!
!!  - ^20.0.0 (Planned end-of-life: 2026-04-30)                               !!
!!  - ^18.0.0 (Planned end-of-life: 2025-04-30)                               !!
!!                                                                            !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 ❌  amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8: destroy failed Error: The stack named amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8 is in a failed state. You may need to delete it from the AWS console : DELETE_FAILED (The following resource(s) failed to delete: [auth179371D7]. )
    at destroyStack (/Users/iwasa.takahito/work/hoge0817amplify/hoge0817amplify/node_modules/aws-cdk/lib/index.js:455:2157)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async CdkToolkit.destroy (/Users/iwasa.takahito/work/hoge0817amplify/hoge0817amplify/node_modules/aws-cdk/lib/index.js:458:207603)
    at async exec4 (/Users/iwasa.takahito/work/hoge0817amplify/hoge0817amplify/node_modules/aws-cdk/lib/index.js:513:54331)
The stack named amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8 is in a failed state. You may need to delete it from the AWS console : DELETE_FAILED (The following resource(s) failed to delete: [auth179371D7]. )

Cause: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!                                                                            !!
!!  Node 21 has reached end-of-life on 2024-06-01 and is not supported.       !!
!!  Please upgrade to a supported node version as soon as possible.           !!
!!                                                                            !!
!!  This software is currently running on node v21.7.1.                       !!
!!  As of the current release of this software, supported node releases are:  !!
!!  - ^22.0.0 (Planned end-of-life: 2027-04-30)                               !!
!!  - ^20.0.0 (Planned end-of-life: 2026-04-30)                               !!
!!  - ^18.0.0 (Planned end-of-life: 2025-04-30)                               !!
!!                                                                            !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 ❌  amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8: destroy failed Error: The stack named amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8 is in a failed state. You may need to delete it from the AWS console : DELETE_FAILED (The following resource(s) failed to delete: [auth179371D7]. )
    at destroyStack (/Users/iwasa.takahito/work/hoge0817amplify/hoge0817amplify/node_modules/aws-cdk/lib/index.js:455:2157)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async CdkToolkit.destroy (/Users/iwasa.takahito/work/hoge0817amplify/hoge0817amplify/node_modules/aws-cdk/lib/index.js:458:207603)
    at async exec4 (/Users/iwasa.takahito/work/hoge0817amplify/hoge0817amplify/node_modules/aws-cdk/lib/index.js:513:54331)
The stack named amplify-amplifyvitereacttemplate-iwasatakahito-sandbox-c16ed1c1a8 is in a failed state. You may need to delete it from the AWS console : DELETE_FAILED (The following resource(s) failed to delete: [auth179371D7]. )

削除に失敗しましたね。上記のようなログが出力されました。
Amplify コンソールのサンドボックス管理画面からも確認や削除が出来るのですが、こちらもみてみましょう。

B95FFDFB-980F-4572-957D-1807579AC817_4_5005_c.jpeg

ステータスが「失敗」になっていますね。なるほどー。

手動で削除保護を無効化して再削除する必要がある

この中途半端なサンドボックス環境を削除するためには削除保護機能をオフにした上で再度サンドボックス環境の削除をする形となります。
まずは無効化しましょう。

A4F434D6-A731-46B6-ABEB-7229B14A33AA_4_5005_c.jpeg

8E6B7F21-2AE6-4C41-9F05-1DA667C522D0.png

上記で Cognito ユーザープールと DynamoDB テーブルの削除保護を無効化出来ました。
Amplify コンソールから再びサンドボックス環境を削除してみます。

990190C3-AD10-444E-A790-1744A5F3B3A3.png

削除することが出来ました。

さいごに

本日は AWS Amplify Gen 2 で Cognito ユーザープールと DynamoDB テーブルの削除保護を有効化してみました。

有効化は出来たのですが、サンドボックスの削除に影響出るのはちょっと面倒ですね。
削除保護機能については運用環境など必要な環境のみ手動でコンソールから有効化したほうが良さそうな気がします。

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.